<template>
  <div class="table-container">
    <el-table
      :data="data"
      :border="setBorder"
      v-bind="$attrs"
      row-key="id"
      stripe
      style="width: 100%"
      v-loading="config.loading"
      @selection-change="onSelectionChange">
      <el-table-column
        type="selection"
        :reserve-selection="true"
        width="30"
        v-if="config.isSelection" />
      <el-table-column
        type="index"
        label="序号"
        width="60"
        v-if="config.isSerialNo" />
      <el-table-column
        v-for="(item, index) in setHeader"
        :key="index"
        show-overflow-tooltip
        :prop="item?.key"
        :width="item?.colWidth"
        :label="item?.title">
        <template v-slot="scope">
          <template v-if="item?.type === 'image'">
            <el-image
              :style="{ width: `${item.width}px`, height: `${item.height}px` }"
              :src="scope.row[item.key]"
              :zoom-rate="1.2"
              :preview-src-list="[scope.row[item.key]]"
              preview-teleported
              fit="cover" />
          </template>
          <template v-else>
            {{ scope.row[item?.key] }}
          </template>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="100" v-if="config.isOperate">
        <template v-slot="scope">
          <el-popconfirm title="确定删除吗？" @confirm="onDelRow(scope.row)">
            <template #reference>
              <el-button text type="primary">删除</el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
      <template #empty>
        <el-empty description="暂无数据" />
      </template>
    </el-table>
    <div class="table-footer mt15">
      <el-pagination
        v-model:current-page="state.page.pageNum"
        v-model:page-size="state.page.pageSize"
        :pager-count="5"
        :page-sizes="[10, 20, 30]"
        :total="config.total"
        layout="total, sizes, prev, pager, next, jumper"
        background
        @size-change="onHandleSizeChange"
        @current-change="onHandleCurrentChange"></el-pagination>
      <div class="table-footer-tool">
        <SvgIcon
          name="iconfont icon-dayin"
          :size="19"
          title="打印"
          @click="onPrintTable" />
        <SvgIcon
          name="iconfont icon-yunxiazai_o"
          :size="22"
          title="导出"
          @click="onImportTable" />
        <SvgIcon
          name="iconfont icon-shuaxin"
          :size="22"
          title="刷新"
          @click="onRefreshTable" />
        <el-popover
          placement="top-end"
          trigger="click"
          transition="el-zoom-in-top"
          popper-class="table-tool-popper"
          :width="300"
          :persistent="false"
          @show="onSetTable">
          <template #reference>
            <SvgIcon
              name="iconfont icon-quanjushezhi_o"
              :size="22"
              title="设置" />
          </template>
          <template #default>
            <div class="tool-box">
              <el-tooltip content="拖动进行排序" placement="top-start">
                <SvgIcon
                  name="fa fa-question-circle-o"
                  :size="17"
                  class="ml11"
                  color="#909399" />
              </el-tooltip>
              <el-checkbox
                v-model="state.checkListAll"
                :indeterminate="state.checkListIndeterminate"
                class="ml10 mr1"
                label="列显示"
                @change="onCheckAllChange" />
              <el-checkbox
                v-model="getConfig.isSerialNo"
                class="ml12 mr1"
                label="序号" />
              <el-checkbox
                v-model="getConfig.isSelection"
                class="ml12 mr1"
                label="多选" />
            </div>
            <el-scrollbar>
              <div ref="toolSetRef" class="tool-sortable">
                <div
                  class="tool-sortable-item"
                  v-for="v in header"
                  :key="v?.key"
                  :data-key="v?.key">
                  <i class="fa fa-arrows-alt handle cursor-pointer"></i>
                  <el-checkbox
                    v-model="v?.isCheck"
                    size="default"
                    class="ml12 mr8"
                    :label="v?.title"
                    @change="onCheckChange" />
                </div>
              </div>
            </el-scrollbar>
          </template>
        </el-popover>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts" name="netxTable">
  import { reactive, computed, nextTick, ref } from 'vue'
  import { ElMessage } from 'element-plus'
  import printJs from 'print-js'
  import table2excel from 'js-table2excel'
  import Sortable from 'sortablejs'
  import { storeToRefs } from 'pinia'
  import { useThemeConfig } from '@/stores/modules/themeConfig'
  import '@/assets/styles/tableTool.scss'

  // 定义父组件传过来的值
  const props = defineProps({
    // 列表内容
    data: {
      type: Array<EmptyObjectType>,
      default: () => []
    },
    // 表头内容
    header: {
      type: Array<EmptyObjectType>,
      default: () => []
    },
    // 配置项
    config: {
      type: Object,
      default: () => {}
    },
    // 打印标题
    printName: {
      type: String,
      default: () => ''
    }
  })

  // 定义子组件向父组件传值/事件
  const emit = defineEmits(['delRow', 'pageChange', 'sortHeader'])

  // 定义变量内容
  const toolSetRef = ref()
  const storesThemeConfig = useThemeConfig()
  const { themeConfig } = storeToRefs(storesThemeConfig)
  const state = reactive({
    page: {
      pageNum: 1,
      pageSize: 10
    },
    selectlist: [] as EmptyObjectType[],
    checkListAll: true,
    checkListIndeterminate: false
  })

  // 设置边框显示/隐藏
  const setBorder = computed(() => {
    return props.config.isBorder ? true : false
  })
  // 获取父组件 配置项（必传）
  const getConfig = computed(() => {
    return props.config
  })
  // 设置 tool header 数据
  const setHeader = computed(() => {
    return props.header.filter((v: any) => v.isCheck)
  })
  // tool 列显示全选改变时
  const onCheckAllChange = <T,>(val: T) => {
    if (val) props.header.forEach((v: any) => (v.isCheck = true))
    else props.header.forEach((v: any) => (v.isCheck = false))
    state.checkListIndeterminate = false
  }
  // tool 列显示当前项改变时
  const onCheckChange = () => {
    const headers = props.header.filter((v: any) => v.isCheck).length
    state.checkListAll = headers === props.header.length
    state.checkListIndeterminate = headers > 0 && headers < props.header.length
  }
  // 表格多选改变时，用于导出
  const onSelectionChange = (val: EmptyObjectType[]) => {
    state.selectlist = val
  }
  // 删除当前项
  const onDelRow = (row: EmptyObjectType) => {
    emit('delRow', row)
  }
  // 分页改变
  const onHandleSizeChange = (val: number) => {
    state.page.pageSize = val
    emit('pageChange', state.page)
  }
  // 分页改变
  const onHandleCurrentChange = (val: number) => {
    state.page.pageNum = val
    emit('pageChange', state.page)
  }
  // 搜索时，分页还原成默认
  const pageReset = () => {
    state.page.pageNum = 1
    state.page.pageSize = 10
    emit('pageChange', state.page)
  }
  // 打印
  const onPrintTable = () => {
    // https://printjs.crabbly.com/#documentation
    // 自定义打印
    let tableTh = ''
    let tableTrTd = ''
    let tableTd: any = {}
    // 表头
    props.header.forEach((v: any) => {
      tableTh += `<th class="table-th">${v.title}</th>`
    })
    // 表格内容
    props.data.forEach((val: any, key) => {
      if (!tableTd[key]) tableTd[key] = []
      props.header.forEach((v: any) => {
        if (v.type === 'text') {
          tableTd[key].push(
            `<td class="table-th table-center">${val[v.key]}</td>`
          )
        } else if (v.type === 'image') {
          tableTd[key].push(
            `<td class="table-th table-center"><img src="${val[v.key]}" style="width:${v.width}px;height:${v.height}px;"/></td>`
          )
        }
      })
      tableTrTd += `<tr>${tableTd[key].join('')}</tr>`
    })
    // 打印
    printJs({
      printable: `<div style=display:flex;flex-direction:column;text-align:center><h3>${props.printName}</h3></div><table border=1 cellspacing=0><tr>${tableTh}${tableTrTd}</table>`,
      type: 'raw-html',
      css: [
        '//at.alicdn.com/t/c/font_2298093_rnp72ifj3ba.css',
        '//unpkg.com/element-plus/dist/index.css'
      ],
      style: `@media print{.mb15{margin-bottom:15px;}.el-button--small i.iconfont{font-size: 12px !important;margin-right: 5px;}}; .table-th{word-break: break-all;white-space: pre-wrap;}.table-center{text-align: center;}`
    })
  }
  // 导出
  const onImportTable = () => {
    if (state.selectlist.length <= 0)
      return ElMessage.warning('请先选择要导出的数据')
    table2excel(
      props.header,
      state.selectlist,
      `${themeConfig.value.globalTitle} ${new Date().toLocaleString()}`
    )
  }
  // 刷新
  const onRefreshTable = () => {
    emit('pageChange', state.page)
  }
  // 设置
  const onSetTable = () => {
    nextTick(() => {
      const sortable = Sortable.create(toolSetRef.value, {
        handle: '.handle',
        dataIdAttr: 'data-key',
        animation: 150,
        onEnd: () => {
          const headerList: EmptyObjectType[] = []
          sortable.toArray().forEach((val: string) => {
            props.header.forEach((v: any) => {
              if (v.key === val) headerList.push({ ...v })
            })
          })
          emit('sortHeader', headerList)
        }
      })
    })
  }

  // 暴露变量
  defineExpose({
    pageReset
  })
</script>

<style scoped lang="scss">
  .table-container {
    display: flex;
    flex-direction: column;
    .el-table {
      flex: 1;
    }
    .table-footer {
      display: flex;
      .table-footer-tool {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        i {
          margin-right: 10px;
          cursor: pointer;
          color: var(--el-text-color-regular);
          &:last-of-type {
            margin-right: 0;
          }
        }
      }
    }
  }
</style>
